package object;

import javax.vecmath.Color3f;

import ray.Ray;
import scene.IntersectionInfo;
import texture.CheckerboardTexture;
import texture.ImageTexture;

import util.Point3D;
import util.Vector3D;

public class HorizontalQuad extends SceneObject {

	private Point3D a, b, c, d;
	private CheckerboardTexture texture;
	private ImageTexture imageTexture;

	public HorizontalQuad(String name, Color3f diffuseColor, Point3D frontLeft,
			float width, float depth) {
		super(name, diffuseColor, 0.0f, 0.0f);

		this.a = frontLeft;
		this.b = new Point3D(frontLeft.getX() + width, frontLeft.getY(),
				frontLeft.getZ());
		this.c = new Point3D(frontLeft.getX() + width, frontLeft.getY(),
				frontLeft.getZ() - depth);
		this.d = new Point3D(frontLeft.getX(), frontLeft.getY(), frontLeft
				.getZ()
				- depth);

		this.texture = new CheckerboardTexture(20, 15, new Color3f(1.0f, 0.0f,
				0.0f), new Color3f(1.0f, 1.0f, 0.0f));
		this.imageTexture = new ImageTexture();
	}

	@Override
	public Point3D getClosestIntersectionPoint(Ray r) {
		// Check for ray pointing in wrong direction
		float yDiff = r.getEnd().getY() - r.getOrigin().getY();
		if (((r.getOrigin().getY() < this.a.getY()) && (yDiff >= 0))
				|| ((r.getOrigin().getY() > this.a.getY()) && (yDiff < 0))) {
			Point3D temp = r.getEnd().minus(r.getOrigin());
			float tDenom = this.getNormalAtPoint(null).dotProduct(temp.getX(),
					temp.getY(), temp.getZ());
			temp = a.multiplyByScalar(-1.0f);
			float d = this.getNormalAtPoint(null).dotProduct(temp.getX(),
					temp.getY(), temp.getZ());
			float tNumer = (d * -1.0f)
					- (this.getNormalAtPoint(null)
							.dotProduct(r.getOrigin().getX(), r.getOrigin()
									.getY(), r.getOrigin().getZ()));
			if (tDenom == 0) {
				return null;
			} else {
				float t = tNumer / tDenom;
				Point3D planeIntersection = r.getOrigin().plus(
						r.getEnd().minus(r.getOrigin()).multiplyByScalar(t));
				if (planeIntersection.getX() >= this.a.getX()
						&& planeIntersection.getX() <= this.b.getX()
						&& planeIntersection.getZ() <= this.a.getZ()
						&& planeIntersection.getZ() >= this.d.getZ()) {
					planeIntersection.setY(planeIntersection.getY() + 0.01f);
					return planeIntersection;
				} else {
					return null;
				}
			}
		} else {
			return null;
		}
	}

	@Override
	public Vector3D getNormalAtPoint(Point3D p) {
		// B - A
		Vector3D AtoB = new Vector3D(a, b);
		// C - A
		Vector3D AtoC = new Vector3D(a, c);
		// normal
		return AtoB.crossProduct(AtoC);
	}

	public Color3f getProceduralColor(IntersectionInfo i) {
		Point3D p = i.getPoint();
		float widthPercent = (p.getX() - this.a.getX())
				/ (this.b.getX() - this.a.getX());
		float depthPercent = (p.getZ() - this.d.getZ())
				/ (this.a.getZ() - this.d.getZ());
		return this.texture.getColor(widthPercent, depthPercent);
	}
	
	public Color3f getImageColor(IntersectionInfo i) {
		Point3D p = i.getPoint();
		float widthPercent = (p.getX() - this.a.getX())
				/ (this.b.getX() - this.a.getX());
		float depthPercent = (p.getZ() - this.d.getZ())
				/ (this.a.getZ() - this.d.getZ());
		return this.imageTexture.getColor(widthPercent, depthPercent);
	}
	
}
